using System.Collections.Generic;
using UnityEngine;

namespace PhysSound
{
	public class PhysSoundMaterial : ScriptableObject
	{
		public int MaterialTypeKey;

		public int FallbackTypeIndex;

		public int FallbackTypeKey;

		public Range RelativeVelocityThreshold;

		public float PitchRandomness = 0.1f;

		public float SlidePitchMod = 0.05f;

		public float SlideVolMultiplier = 1f;

		public float ImpactNormalBias = 1f;

		public float ScaleMod = 0.15f;

		public LayerMask CollisionMask = -1;

		public bool UseCollisionVelocity = true;

		public bool ScaleImpactVolume = true;

		public List<PhysSoundAudioSet> AudioSets = new List<PhysSoundAudioSet>();

		private Dictionary<int, PhysSoundAudioSet> audioSetDic;

		private void OnEnable()
		{
			if (AudioSets.Count > 0)
			{
				audioSetDic = new Dictionary<int, PhysSoundAudioSet>();
				foreach (PhysSoundAudioSet audioSet in AudioSets)
				{
					if (audioSetDic.ContainsKey(audioSet.Key))
					{
						UnityEngine.Debug.LogError("PhysSound Material " + base.name + " has duplicate audio set for Material Type \"" + PhysSoundTypeList.GetKey(audioSet.Key) + "\". It will not be used during runtime.");
					}
					else
					{
						audioSetDic.Add(audioSet.Key, audioSet);
					}
				}
				if (FallbackTypeIndex == 0)
				{
					FallbackTypeKey = -1;
				}
				else
				{
					FallbackTypeKey = AudioSets[FallbackTypeIndex - 1].Key;
				}
			}
		}

		public AudioClip GetImpactAudio(GameObject otherObject, Vector3 relativeVel, Vector3 norm, Vector3 contact, int layer = -1)
		{
			if (audioSetDic == null)
			{
				return null;
			}
			if (!CollideWith(otherObject))
			{
				return null;
			}
			PhysSoundMaterial physSoundMaterial = null;
			PhysSoundBase component = otherObject.GetComponent<PhysSoundBase>();
			if ((bool)component)
			{
				physSoundMaterial = component.GetPhysSoundMaterial(contact);
			}
			if (UseCollisionVelocity)
			{
				float impactVolume = GetImpactVolume(relativeVel, norm);
				if (impactVolume < 0f)
				{
					return null;
				}
				if ((bool)physSoundMaterial)
				{
					if (audioSetDic.TryGetValue(physSoundMaterial.MaterialTypeKey, out PhysSoundAudioSet value))
					{
						return value.GetImpact(impactVolume, random: false);
					}
					if (FallbackTypeKey != -1)
					{
						return audioSetDic[FallbackTypeKey].GetImpact(impactVolume, random: false);
					}
				}
				else if (FallbackTypeKey != -1)
				{
					return audioSetDic[FallbackTypeKey].GetImpact(impactVolume, random: false);
				}
			}
			else if ((bool)physSoundMaterial)
			{
				if (audioSetDic.TryGetValue(physSoundMaterial.MaterialTypeKey, out PhysSoundAudioSet value2))
				{
					return value2.GetImpact(0f, random: true);
				}
				if (FallbackTypeKey != -1)
				{
					return audioSetDic[FallbackTypeKey].GetImpact(0f, random: true);
				}
			}
			else if (FallbackTypeKey != -1)
			{
				return audioSetDic[FallbackTypeKey].GetImpact(0f, random: true);
			}
			return null;
		}

		public float GetSlideVolume(Vector3 relativeVel, Vector3 norm)
		{
			float num = (!(norm == Vector3.zero)) ? (1f - Mathf.Abs(Vector3.Dot(norm, relativeVel))) : 1f;
			float val = num * relativeVel.magnitude * SlideVolMultiplier;
			return RelativeVelocityThreshold.Normalize(val);
		}

		public float GetImpactVolume(Vector3 relativeVel, Vector3 norm)
		{
			float num = (!(norm == Vector3.zero)) ? Mathf.Abs(Vector3.Dot(norm.normalized, relativeVel.normalized)) : 1f;
			float num2 = (num + (1f - num) * (1f - ImpactNormalBias)) * relativeVel.magnitude;
			if (num2 < RelativeVelocityThreshold.Min)
			{
				return -1f;
			}
			return RelativeVelocityThreshold.Normalize(num2);
		}

		public float GetRandomPitch()
		{
			return UnityEngine.Random.Range(0f - PitchRandomness, PitchRandomness);
		}

		public float GetScaleModPitch(Vector3 scale)
		{
			return 1f - ScaleMod + 1.73205078f / scale.magnitude * ScaleMod;
		}

		public float GetScaleModVolume(Vector3 scale)
		{
			return 1f - ScaleMod + scale.magnitude / 1.73205078f * ScaleMod;
		}

		public bool HasAudioSet(int keyIndex)
		{
			foreach (PhysSoundAudioSet audioSet in AudioSets)
			{
				if (audioSet.CompareKeyIndex(keyIndex))
				{
					return true;
				}
			}
			return false;
		}

		public PhysSoundAudioSet GetAudioSet(int keyIndex)
		{
			foreach (PhysSoundAudioSet audioSet in AudioSets)
			{
				if (audioSet.CompareKeyIndex(keyIndex))
				{
					return audioSet;
				}
			}
			return null;
		}

		public string[] GetFallbackAudioSets()
		{
			string[] array = new string[AudioSets.Count + 1];
			array[0] = "None";
			for (int i = 0; i < AudioSets.Count; i++)
			{
				array[i + 1] = PhysSoundTypeList.GetKey(AudioSets[i].Key);
			}
			return array;
		}

		public bool CollideWith(GameObject g)
		{
			return ((1 << g.layer) & CollisionMask.value) != 0;
		}
	}
}
